package com.yxuan.springboot.intercepter;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yxuan.springboot.model.AdminLogin;
import com.yxuan.springboot.model.UserLogin;
import com.yxuan.springboot.service.AdminLoginService;
import com.yxuan.springboot.service.UserLoginService;
import com.yxuan.springboot.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @className: SysInterceptor.java
 * @methodName: SysInterceptor
 * @effect: 拦截器 用户权限校验
 * @author: JingxuanFan
 * @date: 2023/3/19 17:25
 **/
//@Component
public class SysInterceptor implements HandlerInterceptor {

    @Autowired
    private UserLoginService userLoginService;
    @Autowired
    private AdminLoginService adminLoginService;
    /*@Autowired
    protected AdministratorService administratorService;*/

    //日志对象
    private final static Logger logger = LoggerFactory.getLogger(SysInterceptor.class);

    //拦截的核心方法
    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            System.out.println("OPTIONS请求放行");
            return true;
        }
        logger.info("执行了拦截的核心方法");
        //获取页面的请求地址
        String contextPath = request.getRequestURI();

        String correctToken = null;


        logger.info("路径" + contextPath);
        //判断请求对象中有没有请求方法
        if (handler instanceof HandlerMethod) {
            //从请求中取到token令牌
            String token = request.getHeader("token");
            String temp = request.getHeader("User-Agent");
            System.out.println(temp);
            logger.info("用户token为" + token);
            //先判断token令牌是否为空,
            if (StringUtils.isEmpty(token)) {
                logger.info("验证失败,签名验证不存在");
                //调用自定义方法print
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json; charset=utf-8");
                PrintWriter out = null;
                JSONObject res = new JSONObject();
                res.put("code", 841);
                res.put("message", "验证失败,签名验证不存在");
                out = response.getWriter();
                out.append(res.toString());

                //  print(response, R.error(SystemConstant.JWT_ERRCODE_NULL,"验证失败,签名验证不存在"));
                return false;
            } else {

                //判断是普通用户还是管理员，再分别查找各自的token
                String roleId = request.getHeader("roleId");
                if (roleId != null) {
                    if (roleId.equals("10")) {  //如果是10表示为普通员工
                        //解析token
                        Claims claims = JwtUtil.parseJWT(token);
                        //获取token中手机号并查询该手机号对应的用户类型role（是管理员还是普通用户）
                        String sub = claims.get("sub", String.class);
                        JsonNode subNode = new ObjectMapper().readTree(sub);
                        String phoneNumber = subNode.get("phoneNumber").asText();
                        UserLogin newLogin = new UserLogin();
                        newLogin.setPhoneNumber(phoneNumber);
                        UserLogin targetLogin = userLoginService.findObjectByPramas(newLogin);
                        correctToken = targetLogin.getToken();


                    } else if (roleId.equals("20")) {   //如果是20表示为管理员
                        //解析token
                        Claims claims = JwtUtil.parseJWT(token);
                        //获取token中手机号并查询该手机号对应的用户类型role（是管理员还是普通用户）
                        String sub = claims.get("sub", String.class);
                        JsonNode subNode = new ObjectMapper().readTree(sub);
                        String userName = subNode.get("userName").asText();
                        AdminLogin adminLogin = new AdminLogin();
                        adminLogin.setUserName(userName);
                        AdminLogin targetAdmin = adminLoginService.findObjectByPramas(adminLogin);
                        correctToken = targetAdmin.getToken();
                    }
                }
                if (contextPath != null) {
                    if (token.equals(correctToken) == true) {
                        logger.info("签名验证通过");
                        return true;
                    } else {
                        logger.info("签名验证不通过,token令牌有误");
                        //调用自定义方法print
                        response.setCharacterEncoding("UTF-8");
                        response.setContentType("application/json; charset=utf-8");
                        PrintWriter out = null;
                        JSONObject res = new JSONObject();
                        res.put("code", 841);
                        res.put("message", "签名验证不通过,token令牌有误");
                        out = response.getWriter();
                        out.append(res.toString());
                        // print(response,R.error("签名验证不通过,token令牌有误"));
                    }
                }
            }
            return false;
        }
        return false;
    }


    //拦截的执行POST请求的方法
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        logger.info("拦截的执行POST请求的方法");
    }

    /**
     * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法将在整个请求完成之后，也就是DispatcherServlet渲染了视图执行，
     * 这个方法的主要作用是用于清理资源的，当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.info("执行了afterCompletion方法");
    }


    /**
     * @methodName print
     * @effect: 自定义响应方法, 将请求处理结果响应回浏览器
     */
    public void print(HttpServletResponse response, Object message) {
        try {
            //设置响应头的响应状态
            response.setStatus(HttpStatus.OK.value());
            //设置响应头的响应内容，并转成UTF8
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            //设置头部信息
            response.setHeader("Cache-Control", "no-cache, must-revalidate");
            //字符输出流
            PrintWriter writer = response.getWriter();
            //将message写入到浏览器当中
            writer.write(message.toString());
            //刷新流
            writer.flush();
            //关闭流
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
